#if DEBUG

using Castle.DynamicProxy;
using FluentlyXml.Core;
using FluentlyXml.Core.DSL;
using FluentlyXml.UnitTests.Core.TestObjects;
using FluentlyXml.UnitTests.Helpers;
using NUnit.Framework;

namespace FluentlyXml.UnitTests.Core
{
	public class BarSerializationTests
	{
		[TestFixture]
		public class When_serializing_single_bar
		{
			private Bar _originalBar;
			private IFluentSerializer _serializer;
			private string _xml;

			[SetUp]
			public void When()
			{
				var factory = new FluentSerializerFactory(x =>
				{
					x.ApplyConfigFrom<BarSerialization>();
				});

				_originalBar = Bar.GetTestBar();

				_serializer = factory.CreateSerializer();

				_xml = _serializer.Serialize(_originalBar).ToString();
			}

			[Test]
			public void Then_it_writes_a_root_node_for_the_bar()
			{
				Assert.That(_xml, Is.StringContaining("<Bar>"));
			}

			[Test]
			public void Then_it_writes_an_element_for_each_property()
			{
				Assert.That(_xml, Is.StringContaining("<CustomId>1</CustomId>"));
				Assert.That(_xml, Is.StringContaining("<Name>Test Bar 1</Name>"));
				Assert.That(_xml, Is.StringContaining("<Label>Bar 1 Label</Label>"));
				Assert.That(_xml, Is.StringContaining("<Value>5000</Value>"));
			}
		}

		[TestFixture]
		public class When_deserializing_single_bar
		{
			private IFluentSerializer _serializer;
			private Bar _originalBar;
			private string _xml;
			private Bar _deserializedBar;
			private IFluentDeserializer _deserializer;

			[SetUp]
			public void When()
			{
				var factory = new FluentSerializerFactory(x =>
				{
					x.ApplyConfigFrom<BarSerialization>();
				});

				_originalBar = Bar.GetTestBar();

				_serializer = factory.CreateSerializer();
				_deserializer = factory.CreateDeserializer();

				_xml = _serializer.Serialize(_originalBar).ToString();

				_deserializedBar = _deserializer.Deserialize<Bar>(_xml);
			}

			[Test]
			public void Then_it_deserializes_a_new_bar()
			{
				Assert.That(_deserializedBar, Is.Not.Null);
			}

			[Test]
			public void Then_it_deserializes_all_properties()
			{
				EqualityTester.AssertEqual(_originalBar, _deserializedBar);
			}
		}

		[TestFixture]
		public class When_serializing_a_proxied_bar
		{
			private Bar _bar;
			private string _xml;

			[SetUp]
			public void When()
			{
				var generator = new ProxyGenerator();
				_bar = (Bar)generator.CreateClassProxy(typeof(Bar));
				_bar.Name = "Test!";

				var factory = new FluentSerializerFactory(x =>
				{
					x.ApplyConfigFrom<BarSerialization>();
				});

				var serializer = factory.CreateSerializer();

				_xml = serializer.Serialize(_bar).ToString();
			}

			[Test]
			public void Then_it_still_serializes_the_proxy_as_a_real_bar()
			{
				Assert.That(_xml, Is.StringContaining("<Bar>"));
			}
		}

		[TestFixture]
		public class When_deserializing_bar_array
		{
			private Bar[] _originalBars;
			private IFluentSerializer _serializer;
			private string _xml;
			private Bar[] _deserializedBars;
			private IFluentDeserializer _deserializer;

			[SetUp]
			public void When()
			{
				var factory = new FluentSerializerFactory(x =>
				{
					x.ApplyConfigFrom<BarSerialization>();
				});

				_serializer = factory.CreateSerializer();
				_deserializer = factory.CreateDeserializer();

				_originalBars = new[] { new Bar { BarId = 1 }, new Bar { BarId = 1 }, new Bar { BarId = 2 } };

				_xml = _serializer.Serialize(_originalBars).ToString();

				_deserializedBars = _deserializer.Deserialize<Bar[]>(_xml);
			}

			[Test]
			public void Serializing_creates_xml()
			{
				Assert.That(_xml, Is.Not.Null);
				Assert.That(_xml, Is.Not.Empty);
			}

			[Test]
			public void Deserializing_bars_returns_array_of_expected_length()
			{
				Assert.That(_deserializedBars.Length, Is.EqualTo(_deserializedBars.Length));
			}

			[Test]
			public void Deserializing_bars_does_not_create_duplicates()
			{
				Assert.That(_deserializedBars[0], Is.SameAs(_deserializedBars[1]));
			}
		}		
	}

	/// <summary> </summary>
	public class BarSerialization : FluentSerializationSpec
	{
		/// <summary> </summary>
		public BarSerialization()
		{
			WhenSerializing<Bar>()
				.SerializeAllAncestorsAsThisType();

			WhenDeserializing<Bar>()
				.DetermineIdentityBy(r => r.BarId);
		}
	}
}

#endif